package Model;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.geom.Rectangle2D;

import javax.swing.JTextArea;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

/** 
 *  L'élément 'text' définit un élément graphique qui consiste à écrire du texte dans un dessin.
 *  
 *  @author Kilian Cousein et Benjamin Tardieu
 */
public class Texte extends MotifRectangulaire
{
//======================================================================//
//============================ Variables ===============================//
//======================================================================//
	
	private String police = "Verdana"; // police du texte
	private int taillePolice = 14; // taille du texte
	private String texte = ""; // valeur du texte
	private int effet = Font.PLAIN; // effet du texte
	private int xSelectionne = 0; // abscisse du point en haut a gauche du texte
	private int ySelectionne = 0; // ordonné du point en haut a gauche du texte
	
	private JTextArea zoneTexte = new JTextArea();
	
//======================================================================//
//========================== Constructeurs =============================//
//======================================================================//

	/**
	 * Crée une nouvelle instance de <i>Texte</i> par default.
	 */
	public Texte()
	{
	}
	
	
	/**
	 * Crée une nouvelle instance de <i>Texte</i> qui sera un clone de <i>motif</i>.
	 *
	 * @param motif
	 */
	public Texte(Motif motif)
	{	
		super(motif);
		Texte m = (Texte) motif;
		
		this.texte = m.texte;
		this.largeur = m.largeur;
		this.hauteur = m.hauteur;
		
		this.police = m.police;
		this.taillePolice = m.taillePolice;
		this.effet = m.effet;
	}
		
		
//======================================================================//
//==================== Écriture méthodes abstraites ====================//
//======================================================================//
	
	@Override
	public Motif nouvelleInstance() 
	{
		Texte texte = new Texte();
		texte.setCouleur(this.couleur);
		texte.setCouleurBordure(this.couleurBordure);
		
		return texte;
	}
	
	
	@Override
	public boolean equals(Object o)
	{
		if(this.getClass() == o.getClass())
		{
			Texte texte = (Texte) o;
			boolean egale = true;
			
			egale &= this.x == texte.x;
			egale &= this.y == texte.y;
			egale &= this.largeurBordure == texte.largeurBordure;
			egale &= this.couleurBordure == texte.couleurBordure;
			egale &= this.opacite == texte.opacite;
			egale &= this.opaciteBordure == texte.opaciteBordure;
			egale &= this.couleur == texte.couleur;
			egale &= this.police == texte.police;
			egale &= this.taillePolice == texte.taillePolice;
			egale &= this.effet == texte.effet;
			egale &= this.texte == texte.texte;
			
			return egale; 
		}
		else
			return false;
	}
	

	@Override
	public void dessinerMotif(Graphics2D g) 
	{
		g.setComposite(java.awt.AlphaComposite.getInstance(java.awt.AlphaComposite.SRC_OVER, this.opacite));
		
		
		g.setFont(new Font(police, effet, taillePolice));
		FontMetrics fontMetrics = g.getFontMetrics();
			if (fontMetrics != null)
			{
				if(texte != null)
				{
					g.setColor(couleur);
					g.drawString(texte, x, y);	
					
					this.recalculerDimension(g);
					g.setColor(Color.black);
				}
			}
			
		g.setComposite(java.awt.AlphaComposite.getInstance(java.awt.AlphaComposite.SRC_OVER, 1.0f));	
	}
	
	public void recalculerDimension(Graphics2D g)
	{
		g.setFont(new Font(police, effet, taillePolice));
		FontMetrics fontMetrics = g.getFontMetrics();
		Rectangle2D l = fontMetrics.getStringBounds(texte, g);
		largeur = (int) l.getWidth();
		hauteur = fontMetrics.getAscent()+fontMetrics.getDescent();
		xSelectionne = this.x;
		ySelectionne = y - fontMetrics.getAscent();
	}
	
	@Override
	public Element enregistrer(Document doc) 
	{
		Element texte = doc.createElement("text");
		texte.setTextContent(this.texte);
		texte.setAttribute("x", ""+this.x);
		texte.setAttribute("y", ""+this.y);
		texte.setAttribute("font-family", this.police);
		texte.setAttribute("font-size", ""+this.taillePolice);
		
		if(this.couleur != null)
			texte.setAttribute("fill", "rgb("+this.couleur.getRed()+","+this.couleur.getGreen()+","+this.couleur.getBlue()+")");
		
		if(this.opacite < 1.0f)
		{
			texte.setAttribute("opacity", ""+this.opacite);
		}
		
		if(this.opaciteBordure < 1.0f)
		{
			texte.setAttribute("opacity-stoke", ""+this.opaciteBordure);
		}
		
		return texte;
	}
		
	
	@Override
	public void dessinerPoignees(Graphics2D g)
	{
		int y = this.y - g.getFontMetrics().getAscent();
		
		float[] dash3 = { 4f, 0f, 2f };
		g.setStroke(new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND, 1.0f, dash3, 2f));
		g.drawRect(this.x, y, this.largeur, this.hauteur);
		
		g.setColor(this.couleur);
	}
	
	
	@Override
	public void redimensionner(int x1, int x2, int y1, int y2)
    {
    	int ecartX = x1 - x2;
    	int ecartY = y1 - y2;
    	int x = this.x, y = this.y;
  
		switch (poigneeSelectionne)
		{
			case AUCUNE_POIGNEE : 
				this.x += ecartX; 
				this.y += ecartY; 
				break;
			case GAUCHE_HAUT_POIGNEE : 
				this.y += ecartY;
				this.x += ecartX;
				this.taillePolice += -ecartY;
				break;
			case DROITE_HAUT_POIGNEE : 
				this.y += ecartY;
				this.taillePolice += -ecartY; 
				break;
			case GAUCHE_BAS_POIGNEE : 
				this.x += ecartX;
				this.taillePolice += ecartY;
				break;
			case DROITE_BAS_POIGNEE : 
				this.taillePolice += ecartY;
				break;
			default : 
				break;
		}
    }
	
	
	@Override
 	public int getHandles(int x, int y) 
	{
		//Pas de poignnées pour un objet de type texte
			return AUCUNE_POIGNEE;
	}
 	
 	
	@Override
	public void faireCorrespondre(int ox, int oy, int x, int y) 
	{
		int xt = x - ox;
		int yt = y - oy;

		if (xt < 0 && yt < 0)
		{
			this.x = x;
			this.y = y;
		}
		else if (xt < 0 && yt > 0)
		{
			this.x = ox + xt;
			this.y = oy;
			this.largeur = -xt;
			this.hauteur = yt;
		}
		else if(xt > 0 && yt < 0)
		{
			this.x = ox;
			this.y = oy + yt;
			this.largeur = xt;
			this.hauteur = -yt;
		}
		else
		{
			this.x = ox;
			this.y = oy;
			this.largeur = xt;
			this.hauteur = yt;
		}
	}
	
	
	@Override
	public boolean contient(Point point)
	{
        return (point.x >= this.x-HANDLE_SIZE ) && (point.y >= this.ySelectionne-HANDLE_SIZE) && (point.x <= this.x + this.largeur+HANDLE_SIZE) && (point.y <= this.ySelectionne +hauteur+HANDLE_SIZE);
	}


	@Override
	public void ouvrir(Node node) 
	{
        Node attribut;
		
		for(int j = 0; j < node.getAttributes().getLength(); j++)
		{			
			attribut = node.getAttributes().item(j);
			
			if(attribut.getNodeName() == "x")
				this.x = Integer.valueOf(attribut.getNodeValue());
			else if(attribut.getNodeName() == "y")
				this.y = Integer.valueOf(attribut.getNodeValue());
			else if(attribut.getNodeName() == "fill")
				this.couleur = this.convertitStringCouleur(attribut.getNodeValue());
			else if(attribut.getNodeName() == "font-family")
				this.police = attribut.getNodeValue();
			else if(attribut.getNodeName() == "font-size")
				this.taillePolice = Integer.valueOf(attribut.getNodeValue());
			else if(attribut.getNodeName() == "opacity")
			{
				this.opacite = Float.valueOf(attribut.getNodeValue());
				this.opaciteBordure = Float.valueOf(attribut.getNodeValue());
			}
			else if(attribut.getNodeName() == "stroke-opacity")
				this.opaciteBordure = Float.valueOf(attribut.getNodeValue());	
		}
		
		this.texte = node.getTextContent();
	}
	
	
	@Override
	public Motif clone()
	{
		return new Texte(this);
	}
	
//======================================================================//
//============================= Méthodes ===============================//
//======================================================================//
	
	@Override
	public String toString()
	{
		String texte = super.toString();
		texte += "texte: "+this.texte+"\n";
		texte += "police: "+this.police+"\n";
		texte += "taille police: "+this.taillePolice+"\n";
		texte += "effet: "+this.effet+"\n";
		
		return texte;
	}
	
	
	public JTextArea getJTextArea() 
	{
		return zoneTexte;
	}

	
	public void majText(Graphics2D g) 
	{
		if (zoneTexte != null)
		{
			this.texte = zoneTexte.getText();
			this.recalculerDimension(g);
		}
	}
	
	
	public void modGras()
	{
		if(effet == Font.BOLD)
			effet = Font.PLAIN;
		else
			effet = Font.BOLD;
		
		zoneTexte.setFont(new Font(police, effet, taillePolice));
		zoneTexte.setForeground(couleur);
	}

	
	public void modItalique()
	{
		if(effet == Font.ITALIC)
			effet=Font.PLAIN;
		else
			effet = Font.ITALIC;
		zoneTexte.setFont(new Font(police, effet, taillePolice));
		zoneTexte.setForeground(couleur);
	}
	

	public void setPolice(Object selectedItem) 
	{
		police = (String) selectedItem;
		zoneTexte.setFont(new Font(police, effet, taillePolice));
		zoneTexte.setForeground(couleur);
	}


//======================================================================//
//========================= Getters et Setters =========================//
//======================================================================//	
	
	/**
	 * @return the police
	 */
	public String getPolice()
	{
		return police;
	}


	/**
	 * @param police the police to set
	 */
	public void setPolice(String police)
	{
		this.police = police;
	}


	/**
	 * @return the taillePolice
	 */
	public int getTaillePolice()
	{
		return taillePolice;
	}


	/**
	 * @param taillePolice the taillePolice to set
	 */
	public void setTaillePolice(int taillePolice)
	{
		this.taillePolice = taillePolice;
		zoneTexte.setFont(new Font(police, effet, taillePolice));

	}


	/**
	 * @return the texte
	 */
	public String getTexte()
	{
		return texte;
	}


	/**
	 * @param texte the texte to set
	 */
	public void setTexte(String texte)
	{
		this.texte = texte;
	}
}